package m3f.factorization;

import org.jblas.DoubleMatrix;

import m3f.computing.ConcurrentTemplate;
import m3f.data.MultimodalDataProvider;
import m3f.matrix.Minibatch;

public class ConcurrentErrorComputation extends ConcurrentTemplate{
	
	private MultimodalDataProvider data;
	private DoubleMatrix P;
	private DoubleMatrix Q;
	private DoubleMatrix G;
	private double omega;
	private double textError;
	private double visualError;
	
	public ConcurrentErrorComputation(MultimodalDataProvider trainingData, DoubleMatrix P, DoubleMatrix Q, DoubleMatrix G, double omega){
		super(trainingData.matrixRows()/trainingData.getMinibatchSize()+1);
		this.data = trainingData;
		this.P = P;
		this.Q = Q;
		this.G = G;
		this.omega = omega;
		textError = 0;
		visualError = 0;
	}

	public double getTextError(){
		return textError;
	}
	
	public double getVisualError(){
		return visualError;
	}
	
	@Override
	public void singleOperation(int reg) {
		Minibatch V, T;
		long s = System.currentTimeMillis();
		synchronized (data) {
			V = data.nextVisual();
			T = data.nextTextual();
		}
		DoubleMatrix A;
		DoubleMatrix H = OnlineJointFactorization.latentRepresentation(V,T,P,Q,G, omega);
		A = Q.mmul(H).subi(T.matrix());
		double te = Math.pow(A.norm2(),2.0);
		A = P.mmul(H).subi(V.matrix());
		double ve = Math.pow(A.norm2(),2.0);
		synchronized (this){
			textError += te;
			visualError += ve;
		}
		System.out.println("Error for minibatch: " + (System.currentTimeMillis()-s) + " ms");
	}
}
